#IP带概述
"""
IP代理指的是让爬虫使用代理IP去爬对方网站
"""

#IP代理的构建实战
"""
import urllib.request
ip="117.95.232.146"
#某些ip失效很快，即取忌用
#小技巧：尽量提取国外的，不要提取国内的！！如果是国内的，失效的概率非常高！！！
proxy_ip = urllib.request.ProxyHandler({
    "http":ip
})
#格式：urllib.request.build_opener(代理ip对象，urllib.request.HTTPHandler)
opener = urllib.request.build_opener(proxy_ip,urllib.request.HTTPHandler)
#安装为全局
urllib.request.install_opener(opener)

url = "https://www.baidu.com/"
#下面分开写的操作有必要的，看最后到底是用什么样的形式写入
pre_data=urllib.request.urlopen(url).read()
data=pre_data.decode('utf-8','ignore')
print(len(data))
#运行结果：urllib.error.URLError: <urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。→→该IP失效了/不稳定

#把数据写入文件
fh = open("C:\\Users\\DELL\\Desktop\\python操作文件夹\\ip_baidu.html","wb")
#未解码的数据（pre_data），以二进制的方式写入，直接写它没有解码的，这样就不会出错了
#如果是已经解码的数据，以"w"(b不要写)写入（data）
fh.write(pre_data)
fh.close()
"""


#IP代理池构建的第一种方案(蛇和代理IP稳定的情况)
"""
import random
import urllib.request

#百度首页反爬了，必须得伪装成浏览器
#用户代理池构建
uapools=[
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",#谷歌浏览器
    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5514.400 QQBrowser/10.1.1614.400",#QQ浏览器
    "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",#IE浏览器
    #好像同一个浏览器的不同模式（搜狗的兼容模式）使用的用户代理也不一样
    #百度搜一下也可以找到别的用户代理地址
]

def ua(random_uapools):
    this_ua=random.choice(random_uapools)
    print(this_ua)
    headers = ("User-Agent",this_ua)
    opener = urllib.request.build_opener()
    opener.addheaders = [headers]
    #安装为全局
    urllib.request.install_opener(opener)


ip_pools = [
    "222.184.59.8",
    "59.38.61.243",
    "222.223.182.66",
]

def ip(pools):
    this_ip = random.choice(pools)
    print(this_ip)
    proxy_ip = urllib.request.ProxyHandler({
        "http": this_ip
    })
    # 格式：urllib.request.build_opener(代理ip对象，urllib.request.HTTPHandler)
    opener = urllib.request.build_opener(proxy_ip, urllib.request.HTTPHandler)
    # 安装为全局
    urllib.request.install_opener(opener)

for i in range(5):
    #由于代理ip非常不稳定，我们有必要建立异常处理
    try:
        ip(ip_pools)
        ua(uapools)
        url = "https://www.baidu.com/"
        pre_data = urllib.request.urlopen(url).read()
        data = pre_data.decode('utf-8', 'ignore')
        print(len(data))
        # 运行结果：urllib.error.URLError: <urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。→→该IP失效了/不稳定

        # 把数据写入文件
        fh = open("C:\\Users\\DELL\\Desktop\\python操作文件夹\\ip_baidu"+str(i)+".html", "wb")
        # 未解码的数据（pre_data），以二进制的方式写入，直接写它没有解码的，这样就不会出错了
        # 如果是已经解码的数据，以"w"(b不要写)写入（data）
        fh.write(pre_data)
        fh.close()
    except Exception as e:
        print(e)
"""

#IP代理池实现的第二种方案：通过接口调用的方式实现IP代理池的构建（适用于代理IP不稳定的情况）
import urllib.request
import random
#import re

#用户代理池构建
uapools=[
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",#谷歌浏览器
    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5514.400 QQBrowser/10.1.1614.400",#QQ浏览器
    "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",#IE浏览器
    #好像同一个浏览器的不同模式（搜狗的兼容模式）使用的用户代理也不一样
    #百度搜一下也可以找到别的用户代理地址
]

def ua(random_uapools):
    this_ua=random.choice(random_uapools)
    print(this_ua)
    headers = ("User-Agent",this_ua)
    opener = urllib.request.build_opener()
    opener.addheaders = [headers]
    #安装为全局
    urllib.request.install_opener(opener)


#通过这个接口有问题，调用ip太慢了！！！，需要重新定义函数
"""
def ip():
    this_ip = urllib.request.urlopen("http://tvp.daxiangdaili.com/ip/?tid=559126871522487&num=1&foreign=only").read().decode("utf-8","ignore")
    print(this_ip)
    proxy_ip = urllib.request.ProxyHandler({
        "http": this_ip
    })
    # 格式：urllib.request.build_opener(代理ip对象，urllib.request.HTTPHandler)
    opener = urllib.request.build_opener(proxy_ip, urllib.request.HTTPHandler)
    # 安装为全局
    urllib.request.install_opener(opener)
"""

#讲课老师的遇到的问题是，在ip函数产生的列表之后，再次调用该函数，上一次产生的ip列表不存在了
#第一种思路：把ip种产生的ip列表定义为全局变量



#第二种思路（老师的）：分成两个函数来写
"""
def ip():
    all_ip = urllib.request.urlopen("http://tvp.daxiangdaili.com/ip/?tid=559126871522487&num=10&foreign=only").read().decode("utf-8","ignore")
    for item in all_ip:
        print(item)
        #读出来是二进制的形式，需要用正则来提取，但是这里解码就直接得到了（为什么需要解码两次就可以了？？明明之前就解码过了？？？不太明白），所以不需要使用正则
        item.decode("utf-8","ignore")
"""
#调用接口
def api():
    print("这一次调用了接口")
    all_ip = urllib.request.urlopen("http://tvp.daxiangdaili.com/ip/?tid=559126871522487&num=10&foreign=only").read().decode("utf-8", "ignore")
    ip_pools=[]#好像必须得先定义才能赋值
    for item in all_ip:
        #读出来是二进制的形式，需要用正则来提取，但是这里解码就直接得到了（为什么需要解码两次就可以了？？明明之前就解码过了？？？不太明白），所以不需要使用正则
        #还是用正则吧，最后结果输出有多余空行
        ip_pools.append(item)#这里的item不能解码→→最好还是得用正则表达式
        #不用正则表达式问题太多了
    return ip_pools

#进行相应的访问
def ip_chose(ip_pools,time):
    this_ip = ip_pools[time]
    print("当前使用的IP是："+this_ip)
    proxy_ip = urllib.request.ProxyHandler({
        "http": this_ip
    })
    # 格式：urllib.request.build_opener(代理ip对象，urllib.request.HTTPHandler)
    opener = urllib.request.build_opener(proxy_ip, urllib.request.HTTPHandler)
    # 安装为全局
    urllib.request.install_opener(opener)



#w我这里就已经同时使用了用户代理池和IP代理池，但是还可以进一步合并
go = 0
for i in range(3):
    #由于代理ip非常不稳定，我们有必要建立异常处理
    try:
        #通过求余来判断，通过接口得到的10个ip是否用完——不等于0不需要调用，否则调用
        time = go % 10
        ip_pools = []
        if time == 0:#或者while time == 0:
            ip_pools = api()
        #这里不需要else：
        #这里超出列表范围的问题，完全是因为我们得到的是一个空的列表，所以自然会超出范围，后面改就行了
        ip_chose(ip_pools,time)
        #构建用户代理池
        ua(uapools)
        url = "https://www.baidu.com/"
        pre_data = urllib.request.urlopen(url).read()
        data = pre_data.decode('utf-8', 'ignore')
        print(len(data))
        # 运行结果：urllib.error.URLError: <urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。→→该IP失效了/不稳定

        # 把数据写入文件
        fh = open("C:\\Users\\DELL\\Desktop\\python操作文件夹\\ip_baidu"+str(i)+".html", "wb")
        # 未解码的数据（pre_data），以二进制的方式写入，直接写它没有解码的，这样就不会出错了
        # 如果是已经解码的数据，以"w"(b不要写)写入（data）
        fh.write(pre_data)
        fh.close()
    except Exception as e:
        print(e)
    finally:go += 1